/**
 * 视频时长工具类
 * 提供视频文件时长获取、格式化等功能
 */
export class VideoDurationUtil {
    /**
     * 错误类型枚举
     */
    static ErrorType = {
        INVALID_FILE: 'INVALID_FILE', // 无效文件
        NOT_VIDEO_FILE: 'NOT_VIDEO_FILE', // 非视频文件
        DURATION_UNAVAILABLE: 'DURATION_UNAVAILABLE', // 无法获取时长
        LOAD_FAILED: 'LOAD_FAILED' // 加载失败
    } as const;

    /**
     * 获取视频文件时长（单位：秒）
     * @param file 视频文件对象
     * @returns Promise<number> 视频时长（秒）
     * @throws {Error} 包含错误类型和消息的错误对象
     */
    static getDuration(file: File): Promise<number> {
        return new Promise((resolve, reject) => {
            // 校验文件有效性
            if (!file || !(file instanceof File)) {
                reject(new Error(JSON.stringify({
                    type: this.ErrorType.INVALID_FILE,
                    message: '无效的文件对象'
                })));
                return;
            }

            // 校验视频类型
            if (!file.type.startsWith('video/')) {
                reject(new Error(JSON.stringify({
                    type: this.ErrorType.NOT_VIDEO_FILE,
                    message: `文件类型${file.type}不是视频格式`
                })));
                return;
            }

            // 创建视频元素
            const video = document.createElement('video');
            video.preload = 'metadata'; // 仅加载元数据，优化性能

            // 生成临时URL
            const objectUrl = URL.createObjectURL(file);

            // 元数据加载完成处理
            const handleLoadedMetadata = () => {
                video.removeEventListener('loadedmetadata', handleLoadedMetadata);
                video.removeEventListener('error', handleError);

                const duration = video.duration;
                URL.revokeObjectURL(objectUrl); // 立即释放资源

                if (isNaN(duration) || duration <= 0) {
                    reject(new Error(JSON.stringify({
                        type: this.ErrorType.DURATION_UNAVAILABLE,
                        message: '无法获取视频时长信息'
                    })));
                } else {
                    resolve(duration);
                }
            };

            // 错误处理
            const handleError = () => {
                video.removeEventListener('loadedmetadata', handleLoadedMetadata);
                video.removeEventListener('error', handleError);
                URL.revokeObjectURL(objectUrl); // 释放资源

                reject(new Error(JSON.stringify({
                    type: this.ErrorType.LOAD_FAILED,
                    message: '视频加载失败，可能是格式不支持或文件损坏'
                })));
            };

            // 绑定事件监听
            video.addEventListener('loadedmetadata', handleLoadedMetadata);
            video.addEventListener('error', handleError);

            // 设置源地址开始加载
            video.src = objectUrl;
        });
    }

    /**
     * 将秒数格式化为时分秒字符串
     * @param seconds 视频时长（秒）
     * @param options 格式化选项
     * @returns 格式化后的时长字符串
     * @example
     * format(3661) → "01:01:01"
     * format(61, { showHours: false }) → "01:01"
     */
    static format(
        seconds: number,
        options: {
            showHours?: boolean; // 是否强制显示小时（默认：自动判断）
            padWithZero?: boolean; // 是否补零（默认：true）
        } = {}
    ): string {
        const { showHours = false, padWithZero = true } = options;

        // 处理无效值
        if (isNaN(seconds) || seconds < 0) return '00:00';

        // 计算时分秒
        const hours = Math.floor(seconds / 3600);
        const minutes = Math.floor((seconds % 3600) / 60);
        const secs = Math.floor(seconds % 60);

        // 格式化数字（补零处理）
        const formatNumber = (num: number) =>
            padWithZero ? num.toString().padStart(2, '0') : num.toString();

        // 组装结果
        if (hours > 0 || showHours) {
            return `${formatNumber(hours)}:${formatNumber(minutes)}:${formatNumber(secs)}`;
        } else {
            return `${formatNumber(minutes)}:${formatNumber(secs)}`;
        }
    }

    /**
     * 解析错误信息
     * @param error 错误对象
     * @returns 包含错误类型和消息的对象
     */
    static parseError(error: unknown): {
        type: keyof typeof VideoDurationUtil.ErrorType;
        message: string;
    } {
        try {
            if (error instanceof Error) {
                const parsed = JSON.parse(error.message);
                if (parsed.type && parsed.message) {
                    return parsed;
                }
            }
        } catch {
            // 解析失败时返回默认错误
        }
        return {
            type: this.ErrorType.LOAD_FAILED,
            message: '获取视频时长时发生未知错误'
        };
    }
}

// 使用示例
/*
// 1. 结合文件选择器使用
const fileInput = document.getElementById('videoInput') as HTMLInputElement;
fileInput.addEventListener('change', async (e) => {
  const file = (e.target as HTMLInputElement).files?.[0];
  if (!file) return;

  try {
    const duration = await VideoDurationUtil.getDuration(file);
    console.log('原始时长（秒）：', duration);
    console.log('格式化时长：', VideoDurationUtil.format(duration));
    console.log('不含小时的格式化：', VideoDurationUtil.format(duration, { showHours: false }));
  } catch (err) {
    const error = VideoDurationUtil.parseError(err);
    console.error(`[${error.type}] ${error.message}`);
    // 根据错误类型处理不同逻辑
    if (error.type === VideoDurationUtil.ErrorType.NOT_VIDEO_FILE) {
      alert('请选择视频文件');
    }
  }
});
*/